# Copyright (c) 2006 Charl P. Botha <http://cpbotha.net/>
# All rights reserved.

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission.

# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from ee_except import EnvEditException, EnvEditWarningException
import envkey
import version
import view

import os
import pywintypes
import sys

class Controller:
    """Main application class.
    """
    
    def __init__(self):
        # setup appdir
        if hasattr(sys, 'frozen') and sys.frozen:
            self._appdir, exe = os.path.split(sys.executable)
        else:
            dirname = os.path.dirname(sys.argv[0])
            if dirname and dirname != os.curdir:
                self._appdir = dirname
            else:
                self._appdir = os.getcwd()

        
        self.user_env = envkey.EnvKey(envkey.CU_ENV_KEYSPEC)
        self.sys_env = envkey.EnvKey(envkey.SYS_ENV_KEYSPEC)

        # create the interface
        self.view = view.View(self)

        # do the initial synchronisation
        # we have to check for errors explicitly, as the view isn't invoking
        # these.
        try:
            self.sync_user_env()
        except EnvEditException, e:
            self.view.show_error(
                'Error',
                'Could not synchronise with USER environment: %s' % (str(e),))

        try:
            self.sync_sys_env()
        except EnvEditException, e:
            self.view.show_error(
                'Error',
                'Could not synchronise with SYSTEM environment: %s' %
                (str(e),))
            

    def apply_user_env(self):
        if self.view.get_user_mode() != view.MODE_PREVIEW:
            raise EnvEditWarningException(
                'You have to be in preview mode before applying.')

        self.user_env.set_text(self.view.get_user_text())

        try:
            self.user_env.apply_changes()
            # after applying changes, we'd like to see it back
            self.sync_user_env()
        except pywintypes.error, e:
            raise EnvEditException(str(e))

    def export_user_to_reg_file(self, filename):
        """Currently unused, as process needs special privileges to do
        registry backup.
        """
        try:
            self.user_env.export_to_reg_file(filename)
        except pywintypes.error, e:
            raise EnvEditException(str(e))
            

    def export_sys_to_reg_file(self, filename):
        """Currently unused, as process needs special privileges to do
        registry backup.
        """
        try:
            self.sys_env.export_to_reg_file(filename)
        except pywintypes.error, e:
            raise EnvEditException(str(e))

    def get_version(self):
        return version.VERSION
            
        
    def preview_user_env(self):
        """Apply the user_env text input to the preview dict, and parse back
        the results to preview the changes that WOULD be made to the registry.
        """

        self.user_env.set_text(self.view.get_user_text(),
                               preview=True)
        self.view.set_user_text(
            self.user_env.get_text(preview=True))
        
        self.view.set_user_mode(view.MODE_PREVIEW)

    def apply_sys_env(self):
        if self.view.get_sys_mode() != view.MODE_PREVIEW:
            raise EnvEditWarningException(
                'You have to be in preview mode before applying.')

        self.sys_env.set_text(self.view.get_sys_text())

        try:
            self.sys_env.apply_changes()
            # after applying changes, we'd like to see it back
            self.sync_sys_env()
        except pywintypes.error, e:
            raise EnvEditException(str(e))

    def get_appdir(self):
        return self._appdir

    def get_resdir(self):
        return os.path.join(self.get_appdir(), 'resources')

    def preview_sys_env(self):
        """Apply the sys_env text input to the preview dict, and parse back
        the results to preview the changes that WOULD be made to the registry.
        """

        self.sys_env.set_text(self.view.get_sys_text(),
                               preview=True)
        self.view.set_sys_text(
            self.sys_env.get_text(preview=True))
        
        self.view.set_sys_mode(view.MODE_PREVIEW)
    

    def quit(self):
        self.view.close()
        
    def sync_user_env(self):
        """Synchronise user environment with the registry and update the
        display.

        @raises EnvEditException: when it can't read the USER environment.
        """

        try:
            self.user_env.sync()
        except pywintypes.error, e:
            raise EnvEditException(str(e))
            
        self.view.set_user_text(self.user_env.get_text())
        self.view.set_user_mode(view.MODE_SYNCED)

    def sync_sys_env(self):
        """Synchronise the system environment with the registry and update
        the display.

        @raises EnvEditException: when it can't read the SYS environment.
        """
        
        try:
            self.sys_env.sync()
        except pywintypes.error, e:
            raise EnvEditException(str(e))
        
        self.view.set_sys_text(self.sys_env.get_text())
        self.view.set_sys_mode(view.MODE_SYNCED)

    def main_loop(self):
        self.view.main_loop()


def main():
    controller = Controller()
    controller.main_loop()
    

if __name__ == '__main__':
    main()

